﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NGinnBPM.Lib.Interfaces;
using NGinnBPM.Lib.Schema;
using NGinnBPM.Lib.Data;
using NLog;
using Jint;

namespace NGinnBPM.Services.Scripting.JintScript
{
    public class JintProcessScriptManager : IProcessScriptManager, System.ComponentModel.ISupportInitialize
    {
        private JintEngine _engine;
        private Logger log = LogManager.GetCurrentClassLogger();
        private Jint.Expressions.Program _initialScript;
        private Dictionary<string, Jint.Expressions.Program> _compiledScripts = new Dictionary<string, Jint.Expressions.Program>();

        public JintProcessScriptManager()
        {
            _engine = new JintEngine();
            _engine.AllowClr = true;
            _engine.DisableSecurity();
            _initialScript = JintEngine.Compile(@"
                return null;
                ", true);
        }

        public void PackageDefinitionUpdated(Lib.Schema.PackageDefinition pd)
        {
            _compiledScripts = new Dictionary<string, Jint.Expressions.Program>();
        }

        public void VerifyPackageScripts(Lib.Schema.PackageDefinition pd)
        {
            
        }

        public ITaskScript GetTaskScript(Lib.Schema.ProcessDefinition pd, string taskId)
        {
            JintTaskScript scr = new JintTaskScript(InitializeNewEngineForProcess(pd), pd, taskId, this);
            return scr;
        }

        private JintEngine InitializeNewEngineForProcess(ProcessDefinition pd)
        {
            JintEngine eng = new JintEngine();
            eng.AllowClr = true;
            eng.DisableSecurity();
            eng.Run(_initialScript);
            return eng;
        }

        public void BeginInit()
        {
            
        }

        public void EndInit()
        {
            
        }

        internal Jint.Expressions.Program GetCompiledScript(string script)
        {
            Jint.Expressions.Program prog;
            lock (_compiledScripts)
            {
                if (_compiledScripts.TryGetValue(script, out prog))
                    return prog;
                else
                {
                    var prg = JintEngine.Compile(script, true);
                    _compiledScripts[script] = prg;
                    return prg;
                }
            }
        }
    }
}
